Skip to content

feat: add staleReloadMode#6921

Merged
schiller-manuel merged 3 commits intomainfrom
feat-staleReloadMode
Mar 14, 2026
Merged

feat: add staleReloadMode#6921
schiller-manuel merged 3 commits intomainfrom
feat-staleReloadMode

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Mar 13, 2026

Summary by CodeRabbit

  • New Features

    • Configurable stale reload modes for route loaders: 'background' (non-blocking) and 'blocking' (waits for fresh data).
    • Router-level default for stale reload behavior and per-route overrides.
    • Loader can be provided as an object with a handler and staleReloadMode.
  • Documentation

    • Guides and API docs updated with examples and semantics for stale reload modes and configuration.
  • Tests

    • Expanded tests covering background vs blocking behavior and object-form loaders.

@changeset-bot
Copy link

changeset-bot bot commented Mar 13, 2026

🦋 Changeset detected

Latest commit: 7ccbfb5

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

This PR adds an object-form loader API with an optional staleReloadMode ('background' | 'blocking'), a router-level defaultStaleReloadMode option, type exports for the new loader shapes, and runtime changes so stale reloads can run in background or block navigation depending on configuration. Tests and docs updated accordingly.

Changes

Cohort / File(s) Summary
Core types & exports
packages/router-core/src/route.ts, packages/router-core/src/index.ts, packages/router-core/src/router.ts
Added LoaderStaleReloadMode, RouteLoaderObject, RouteLoaderEntry, ResolveRouteLoaderFn and expanded loader-related typing. Exported new types and added defaultStaleReloadMode option on RouterOptions.
Loader runtime behavior
packages/router-core/src/load-matches.ts
Refactored loader resolution to accept function or object-form loaders, unified invocation path, and introduced shouldReloadInBackground (derived from per-route staleReloadMode or router defaultStaleReloadMode) which alters async/background vs blocking loader execution and boundary/notFound handling.
File route type updates
packages/react-router/src/fileRoute.ts, packages/solid-router/src/fileRoute.ts, packages/vue-router/src/fileRoute.ts
Replaced usages/imports of RouteLoaderFn with the new RouteLoaderEntry type in FileRouteLoader generics to accept the object-form loader shape.
Documentation
docs/router/api/router/RouteOptionsType.md, docs/router/api/router/RouterOptionsType.md, docs/router/guide/data-loading.md
Documented object-form loader ({ handler, staleReloadMode }), new defaultStaleReloadMode RouterOptions, guide updates explaining background vs blocking semantics, defaults, and interactions with staleTime.
Tests & metadata
.changeset/poor-dryers-stare.md, packages/router-core/tests/load.test.ts
Added changeset entry and substantially expanded tests to cover object-form loaders, default vs per-loader staleReloadMode, background vs blocking scenarios, and introduced test timers/fixtures to validate behavior.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped through routes both bright and gray,
I wrapped my handler up in play—
Background snoozes, blocking waits,
Choose your pace at routing gates,
Hooray, loaders dance and save the day! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add staleReloadMode' directly and accurately describes the main feature addition across the changeset: introducing a new staleReloadMode configuration option for controlling loader reload behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-staleReloadMode
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Mar 13, 2026

View your CI Pipeline Execution ↗ for commit 7ccbfb5

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 8m 47s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 55s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-14 00:22:56 UTC

@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

Bundle Size Benchmarks

  • Commit: 79cd4d5afa22
  • Measured at: 2026-03-14T00:15:08.881Z
  • Baseline source: history:6069eba64369
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.13 KiB +46 B (+0.05%) 274.22 KiB 75.76 KiB ▂▂▂▂▂▂▂▂▂▂▁█
react-router.full 90.13 KiB +62 B (+0.07%) 284.48 KiB 78.44 KiB ▂▂▂▂▂▂▂▂▂▂▁█
solid-router.minimal 36.48 KiB +58 B (+0.16%) 109.43 KiB 32.81 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-router.full 40.80 KiB +53 B (+0.13%) 122.40 KiB 36.66 KiB ▁▁▁▁▁▁▁▁▁▁▁█
vue-router.minimal 52.35 KiB +61 B (+0.11%) 149.47 KiB 47.02 KiB ▁▁▁▁▁▁▁▁▁▁▁█
vue-router.full 57.14 KiB +63 B (+0.11%) 164.98 KiB 51.26 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.minimal 99.71 KiB +61 B (+0.06%) 313.37 KiB 86.21 KiB ▂▂▂▂▂▂▂▂▂▂▁█
react-start.full 103.02 KiB +55 B (+0.05%) 323.10 KiB 89.08 KiB ▂▂▂▂▂▂▂▂▂▂▁█
solid-start.minimal 48.79 KiB +43 B (+0.09%) 147.02 KiB 43.13 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-start.full 54.26 KiB +52 B (+0.09%) 162.88 KiB 47.81 KiB ▁▁▁▁▁▁▁▁▁▁▁█

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 13, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@6921

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@6921

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@6921

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@6921

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@6921

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@6921

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@6921

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@6921

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@6921

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@6921

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@6921

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@6921

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@6921

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@6921

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@6921

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@6921

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@6921

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@6921

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@6921

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@6921

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@6921

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@6921

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@6921

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@6921

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@6921

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@6921

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@6921

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@6921

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@6921

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@6921

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@6921

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@6921

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@6921

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@6921

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@6921

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@6921

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@6921

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@6921

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@6921

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@6921

commit: 3fb7789

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/router-core/src/route.ts (1)

1044-1070: ⚠️ Potential issue | 🟡 Minor

BaseRoute.updateLoader() still rejects the new loader object shape.

This widens RouteOptions.loader to accept { handler, staleReloadMode }, but BaseRoute.updateLoader() later in this file is still typed as RouteLoaderFn only. That leaves the imperative path requiring a cast for the new feature instead of accepting it natively.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/src/route.ts` around lines 1044 - 1070,
BaseRoute.updateLoader() is still typed to accept only RouteLoaderFn which
rejects the new object-shape loader; change updateLoader's parameter type to the
same union used for the loader property (i.e. Constrain<TLoaderFn,
RouteLoaderFn<...> | RouteLoaderObject<...>> or the shared alias used for
RouteOptions.loader) so it natively accepts both function and object loaders;
update any related generics on BaseRoute.updateLoader to match
TLoaderDeps/TLoaderFn/TRegister/etc. and adjust internal handling to accept the
object shape where currently only RouteLoaderFn is assumed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.changeset/poor-dryers-stare.md:
- Around line 1-3: The changeset only bumps '@tanstack/router-core' but the PR
also changes the public file-route loader API in
packages/react-router/src/fileRoute.ts (the new object-form loader typing), so
add a corresponding changeset entry for '@tanstack/react-router' describing this
API change; update .changeset to include a minor (or appropriate) release for
'@tanstack/react-router' and reference the file-route loader typing change so
consumers get the published typing update.

---

Outside diff comments:
In `@packages/router-core/src/route.ts`:
- Around line 1044-1070: BaseRoute.updateLoader() is still typed to accept only
RouteLoaderFn which rejects the new object-shape loader; change updateLoader's
parameter type to the same union used for the loader property (i.e.
Constrain<TLoaderFn, RouteLoaderFn<...> | RouteLoaderObject<...>> or the shared
alias used for RouteOptions.loader) so it natively accepts both function and
object loaders; update any related generics on BaseRoute.updateLoader to match
TLoaderDeps/TLoaderFn/TRegister/etc. and adjust internal handling to accept the
object shape where currently only RouteLoaderFn is assumed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e8bf373f-f4bb-4e4b-8cb9-8b56979c5573

📥 Commits

Reviewing files that changed from the base of the PR and between 79cd4d5 and 7a60354.

📒 Files selected for processing (10)
  • .changeset/poor-dryers-stare.md
  • docs/router/api/router/RouteOptionsType.md
  • docs/router/api/router/RouterOptionsType.md
  • docs/router/guide/data-loading.md
  • packages/react-router/src/fileRoute.ts
  • packages/router-core/src/index.ts
  • packages/router-core/src/load-matches.ts
  • packages/router-core/src/route.ts
  • packages/router-core/src/router.ts
  • packages/router-core/tests/load.test.ts

Comment on lines +1 to +3
---
'@tanstack/router-core': minor
---
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a @tanstack/react-router changeset here too.

This PR also changes the public file-route loader API in packages/react-router/src/fileRoute.ts. Releasing only @tanstack/router-core would leave @tanstack/react-router consumers without a published version that includes the new object-form loader typing.

Suggested changeset update
 ---
 '@tanstack/router-core': minor
+'@tanstack/react-router': minor
 ---
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---
'@tanstack/router-core': minor
---
---
'@tanstack/router-core': minor
'@tanstack/react-router': minor
---
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/poor-dryers-stare.md around lines 1 - 3, The changeset only bumps
'@tanstack/router-core' but the PR also changes the public file-route loader API
in packages/react-router/src/fileRoute.ts (the new object-form loader typing),
so add a corresponding changeset entry for '@tanstack/react-router' describing
this API change; update .changeset to include a minor (or appropriate) release
for '@tanstack/react-router' and reference the file-route loader typing change
so consumers get the published typing update.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 13, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing feat-staleReloadMode (7ccbfb5) with main (6069eba)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (79cd4d5) during the generation of this report, so 6069eba was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.changeset/poor-dryers-stare.md (1)

1-5: ⚠️ Potential issue | 🟠 Major

Release the framework router packages too.

This expands the earlier @tanstack/react-router changeset concern: the same public typing change also lands in packages/solid-router/src/fileRoute.ts and packages/vue-router/src/fileRoute.ts. If the @tanstack/*-core entries are intentional, please add @tanstack/react-router, @tanstack/solid-router, and @tanstack/vue-router too so the new RouteLoaderEntry API ships to wrapper consumers.

Suggested changeset update
 ---
 '@tanstack/router-core': minor
 '@tanstack/react-core': minor
 '@tanstack/solid-core': minor
 '@tanstack/vue-core': minor
+'@tanstack/react-router': minor
+'@tanstack/solid-router': minor
+'@tanstack/vue-router': minor
 ---
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/poor-dryers-stare.md around lines 1 - 5, The changeset currently
bumps '@tanstack/router-core', '@tanstack/react-core', '@tanstack/solid-core',
and '@tanstack/vue-core' but omits the corresponding wrapper packages that also
changed typing; update the changeset to include '@tanstack/react-router',
'@tanstack/solid-router', and '@tanstack/vue-router' with the same "minor"
release so the new RouteLoaderEntry API (the public typing change referenced) is
published to wrapper consumers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.changeset/poor-dryers-stare.md:
- Around line 1-5: The changeset currently bumps '@tanstack/router-core',
'@tanstack/react-core', '@tanstack/solid-core', and '@tanstack/vue-core' but
omits the corresponding wrapper packages that also changed typing; update the
changeset to include '@tanstack/react-router', '@tanstack/solid-router', and
'@tanstack/vue-router' with the same "minor" release so the new RouteLoaderEntry
API (the public typing change referenced) is published to wrapper consumers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46f957b8-e085-4890-9365-6bb8324090a1

📥 Commits

Reviewing files that changed from the base of the PR and between 7a60354 and 7ccbfb5.

📒 Files selected for processing (3)
  • .changeset/poor-dryers-stare.md
  • packages/solid-router/src/fileRoute.ts
  • packages/vue-router/src/fileRoute.ts

@schiller-manuel schiller-manuel merged commit 6f297a2 into main Mar 14, 2026
15 checks passed
@schiller-manuel schiller-manuel deleted the feat-staleReloadMode branch March 14, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant